﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace ToolBtn
{
    public partial class ToolBtn : UserControl
    {
        #region 参数
        public delegate void BtnClickHandle(object obj, string name);
        public event BtnClickHandle OnBtnClicked;
        /// <summary>
        /// 鼠标点击前选中按钮
        /// </summary>
        int OldIndex = 0;
        public List<BtnBase> ToolBtns;
        List<BtnBase> ShowBtns = new List<BtnBase>();
        private Color boderColor = Color.FromArgb(201, 201, 201);//Color.FromArgb(80, 80, 80);
        /// <summary>
        /// 边线颜色
        /// </summary>
        public Color BoderColor
        {
            get { return boderColor; }
            set { boderColor = value; }
        }
        private Color backColor = Color.FromArgb(255, 255, 255);//Color.FromArgb(44, 44, 44);
        /// <summary>
        /// 背景色
        /// </summary>
        public Color BackColors
        {
            get { return backColor; }
            set { backColor = value; }
        }
        private Color selectBackColor = Color.FromArgb(220, 220, 220);//Color.FromArgb(20, 20, 20);
        /// <summary>
        /// 选中背景色
        /// </summary>
        public Color SelectBackColor
        {
            get { return selectBackColor; }
            set { selectBackColor = value; }
        }
        private Font font = new Font("宋体", 9, FontStyle.Regular);
        private int spacing = 12;
        /// <summary>
        /// 两边留白
        /// </summary>
        public int Spacing
        {
            get { return spacing; }
            set { spacing = value; }
        }
        private int btnWidth = 68;
        /// <summary>
        /// 高度
        /// </summary>
        public int BtnWidth
        {
            get { return btnWidth; }
            set { btnWidth = value; }
        }
        public Image MoreImage;
        private int selectIndex = -1;
        /// <summary>
        /// 当前选中按钮号
        /// </summary>
        public int SelectIndex
        {
            get { return selectIndex; }
            set
            {
                selectIndex = value;
            }
        }
        bool IsHover = false;
        int HoverIndex = 0;
        int OffsetW = 2;
        #endregion

        #region 构造函数
        public ToolBtn()
        {
            InitializeComponent();
            ToolBtns = new List<BtnBase>();
            this.ForeColor = Color.Black;
            this.Height = 24;
            SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
        }
        #endregion

        #region 重绘函数
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            for (int i = 0; i < ShowBtns.Count; i++)
            {
                DrawBtn(e.Graphics, i);
            }
        }
        #endregion

        public BtnBase Add(string text, string name = null, Image image = null,string tips = null, bool isShowSp = false)
        {
            BtnBase btn = new BtnBase(this) { Text = text, Name = name == null ? text : name, Image = image, Tips = tips, IsShowLine = isShowSp };
            btn.OnBtnClicked += btn_OnBtnClicked;
            ToolBtns.Add(btn);
            return btn;
        }


        public void Add(BtnBase btn)
        {
            btn.OnBtnClicked += btn_OnBtnClicked;
            ToolBtns.Add(btn);
        }

        void btn_OnBtnClicked(object obj, string name)
        {
            if (OnBtnClicked != null)
            {
                OnBtnClicked(obj, name);
            }
        }

        /// <summary>
        /// 改变宽度时重新计算显示的按钮数量
        /// </summary>
        /// <param name="length"></param>
        public void DealWidth(int length)
        {
            if (length > 0)
            {
                bool isFold = length < ToolBtns.Count * BtnWidth;
                int ShowNum = Math.Min(ToolBtns.Count, length / BtnWidth - (isFold ? 1 : 0));
                ShowBtns.Clear();
                for (int i = 0; i < ShowNum; i++)
                {
                    ShowBtns.Add(ToolBtns[i]);
                }
                //如果折叠,添加更多按钮
                if (isFold && ShowNum >= 0)
                {
                    BtnPopup btn = new BtnPopup(this);
                    btn.OnBtnClicked += btn_OnBtnClicked;
                    for (int i = ShowNum; i < ToolBtns.Count; i++)
                    {
                        btn.AddChild(ToolBtns[i]);
                    }
                    btn.Text = btn.Name = "更多";
                    btn.Image = MoreImage;
                    ShowBtns.Add(btn);
                }
                this.Width = ShowBtns.Count * BtnWidth + 1;
                this.Invalidate();
            }
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            DealWidth(Size.Width);
        }

        /// <summary>
        /// 绘制按钮
        /// </summary>
        /// <param name="g"></param>
        /// <param name="i"></param>
        void DrawBtn(Graphics g, int i)
        {
            BtnBase btn = ShowBtns[i];
            Rectangle rec = new Rectangle(i * BtnWidth, 0, BtnWidth, Height - 1);
            Color BgColor = i == SelectIndex ? SelectBackColor : BackColors;
            using (Brush iBrush = new SolidBrush(BgColor))
            {
                g.FillRectangle(iBrush, rec);
                iBrush.Dispose();
            }
            using (Pen iPen = new Pen(BoderColor))
            {
                g.DrawRectangle(iPen, rec);
                iPen.Dispose();
            }
            Size TextSize = TextRenderer.MeasureText(btn.Text, font);
            Color TextColor = i == SelectIndex ? Color.FromArgb(217,128,1) : Color.FromArgb(190, 190, 190);
            using (Brush iBrush = new SolidBrush(ForeColor))
            {
                if (btn.Image == null)
                {
                    g.DrawString(btn.Text, font, iBrush, new Point((BtnWidth - TextSize.Width) / 2 + BtnWidth * i + OffsetW, (Height - TextSize.Height) / 2));
                }
                else
                {
                    int width = (BtnWidth - (btn.Image.Width + TextSize.Width)) / 2;
                    if (btn.IsImageFirst)
                    {
                        g.DrawImage(btn.Image, new Point(width + BtnWidth * i, (Height - btn.Image.Height) / 2));
                        g.DrawString(btn.Text, font, iBrush, new Point(width + btn.Image.Width + BtnWidth * i, (Height - TextSize.Height) / 2));
                    }
                    else
                    {
                        g.DrawString(btn.Text, font, iBrush, new Point(width + BtnWidth * i, (Height - TextSize.Height) / 2));
                        g.DrawImage(btn.Image, new Point(width + TextSize.Width + BtnWidth * i, (Height - btn.Image.Height) / 2));
                    }
                }
                iBrush.Dispose();
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            //this.Width = ToolBtns.Count * BtnWidth + 1;
        }

        int GetEnterNum(string s)
        {
            int num = 1;
            for (int i = 0; i < s.Length;i++)
            {
                if (s[i] == 13)
                {
                    num++;
                }
            }
            return num;
        }

        #region 鼠标响应事件
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (IsHover)
            {
                int index = e.X / BtnWidth;
                if (index != HoverIndex)
                {
                    if (index < ShowBtns.Count && index >= 0)
                    {
                        HoverIndex = index;
                        if (!string.IsNullOrEmpty(ToolBtns[HoverIndex].Tips))
                            toolTip.Show(ToolBtns[HoverIndex].Tips, this, HoverIndex * BtnWidth, -17 * GetEnterNum(ToolBtns[HoverIndex].Tips) - 6);
                        else
                            toolTip.Hide(this);
                    }
                }
            }
        }

        protected override void OnMouseHover(EventArgs e)
        {
            base.OnMouseHover(e);
            IsHover = true;
            if (!string.IsNullOrEmpty(ToolBtns[HoverIndex].Tips))
                toolTip.Show(ToolBtns[HoverIndex].Tips, this, HoverIndex * BtnWidth, -17 * GetEnterNum(ToolBtns[HoverIndex].Tips) - 6);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            IsHover = false;
            toolTip.Hide(this);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (e.Button == MouseButtons.Left)
            {
                if (e.Y <= Height && e.Y >= 0)
                {
                    SelectIndex = e.X / BtnWidth;
                    if (e.X >= 0 && e.X < this.Width)
                    {
                        ShowBtns[SelectIndex].Click(SelectIndex * BtnWidth, Height);
                    }
                    else
                        SelectIndex = OldIndex;
                }
                else
                    SelectIndex = OldIndex;
                this.Invalidate();
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left)
            {
                OldIndex = SelectIndex;
                SelectIndex = e.X / BtnWidth;
                this.Invalidate();
            }
        }
        #endregion
    }

    /// <summary>
    /// 弹出菜单按钮
    /// </summary>
    public class BtnPopup : BtnBase
    {
        List<BtnBase> ChildBtns = new List<BtnBase>();
        ContextMenuStrip contextMenuStrip = new ContextMenuStrip();
        public override event BtnClickHandle OnBtnClicked;

        /// <summary>
        /// 递归添加菜单
        /// </summary>
        /// <param name="baseItem"></param>
        /// <param name="btn"></param>
        void AddStrip(ToolStripItemCollection baseItem, BtnBase btn)
        {
            if (btn is BtnPopup)
            {
                BtnPopup bp = btn as BtnPopup;
                if (bp.ChildBtns != null && bp.ChildBtns.Count > 0)
                {
                    ToolStripMenuItem items = new ToolStripMenuItem(bp.Text);
                    items.Image = bp.Image;
                    items.Name = bp.Name;
                    items.Tag = bp.Tag;
                    foreach (BtnBase bb in bp.ChildBtns)
                    {
                        AddStrip(items.DropDownItems, bb);
                    }
                    baseItem.Add(items);
                }
            }
            else
            {
                ToolStripItem item = baseItem.Add(btn.Text);
                item.Image = btn.Image;
                item.Name = btn.Name;
                item.Tag = btn.Tag;
                item.Click += item_Click;
            }
        }

        public void AddChild(BtnBase btn)
        {
            ChildBtns.Add(btn);
            AddStrip(contextMenuStrip.Items, btn);
            if (btn.IsShowLine)
                contextMenuStrip.Items.Add(new ToolStripSeparator());
        }

        void AddBtn(ToolStripItemCollection items, BtnBase btn)
        {
            ToolStripItem item = items.Add(btn.Text);
            item.Image = btn.Image;
            item.Name = btn.Name;
            item.Tag = btn.Tag;
            item.Click += item_Click;
        }

        public void ClearChildBtn()
        {
            ChildBtns.Clear();
            contextMenuStrip.Items.Clear();
        }

        public override void Click(int x,int y)
        {
            contextMenuStrip.Show(control, x, y);
        }

        public BtnPopup(Control ctrl) : base(ctrl)
        {
            //contextMenuStrip.Renderer = new ToolStripRendererEx();
            IsImageFirst = false;
        }

        void item_Click(object sender, EventArgs e)
        {
            ToolStripItem item = sender as ToolStripItem;
            if (item != null)
            {
                if (OnBtnClicked != null)
                {
                    OnBtnClicked(item.Tag, item.Name);
                }
            }
        }
    }

    public class BtnBase
    {
        public string Text { get; set; }
        public string Name { get; set; }
        public Image Image { get; set; }
        public string Tips { get; set; }
        public object Tag { get; set; }
        public bool IsShowLine = false;
        public bool IsImageFirst = true;
        public Control control;

        public delegate void BtnClickHandle(object obj, string name);
        public virtual event BtnClickHandle OnBtnClicked;

        public BtnBase(Control ctrl)
        {
            control = ctrl;
        }

        public virtual void Click(int x,int y)
        {
            if (OnBtnClicked != null)
            {
                OnBtnClicked(Tag, Name);
            }
        }
    }
}
